home *** CD-ROM | disk | FTP | other *** search
- |##########|
- |#MAGIC #|BOPDNOJA
- |#PROJECT #|"FunctionPlotter"
- |#PATHS #|"EGSProject"
- |#FLAGS #|xx---x--x---x-x-----------------
- |#USERSW #|--------------------------------
- |#USERMASK#|--------------------------------
- |#SWITCHES#|x----x----------
- |##########|
- IMPLEMENTATION MODULE Render;
-
- FROM EGS IMPORT CLUEntry;
- FROM EGSGfx AS G IMPORT RastPortPtr;
- FROM EGSBlit IMPORT ClipRect,WritePixel;
- FROM EGSGadBox IMPORT ResBox;
- IMPORT EGSIntui AS I;
- FROM OFunctions IMPORT Function;
- FROM VectorLongreal IMPORT All;
-
- PROCEDURE CheckFunction(REF str : STRING):INTEGER;
- BEGIN
- RETURN OFunctions.CheckFunction(str,"x","y");
- END CheckFunction;
-
- TYPE
- ConvParams = RECORD
- rotateNScale : Matrix;
- add : Vector;
- dz : LONGREAL;
- x,y : INTEGER;
- light : Vector;
- END;
-
- LightVecsType = ARRAY LightDirs OF Vector;
-
- CONST
- pi = 4.*ATAN(1.);
- pi180 = pi/180.;
-
- LightVects = LightVecsType:(( 0.0,1.0,0.0),
- ( 0.0,1.0,4.0),
- ( 2.0,1.0,4.0),
- (-2.0,1.0,4.0));
-
-
- PROCEDURE CalcConvParams(REF area : ResBox;
- REF func : FuncParams;
- REF draw : DrawParams):ConvParams;
- VAR m : Matrix;
- cz,sz,
- cx,sx : LONGREAL;
-
- mx,my,mz : LONGREAL;
- d : LONGREAL;
- BEGIN
- cz:=COS(LONGREAL(draw.bearing)*pi180);
- sz:=SIN(LONGREAL(draw.bearing)*pi180);
- cx:=COS(LONGREAL(draw.pitch)*pi180);
- sx:=SIN(LONGREAL(draw.pitch)*pi180);
-
- d:=SQRT(LONGREAL(area.w-16)^2.+LONGREAL(area.h-16)^2.)/SQRT(2.);
-
- mx:=d/(func.maxX-func.minX);
- my:=d/(func.maxY-func.minY);
- mz:=d/(func.maxZ-func.minZ);
-
- RESULT.add[0]:=-func.maxX/2.-func.minX/2.;
- RESULT.add[1]:=-func.maxY/2.-func.minY/2.;
- RESULT.add[2]:=-func.maxZ/2.-func.minZ/2.;
-
- WITH RESULT.rotateNScale AS m DO
- m[0,0]:= mx*cz;
- m[0,1]:= mx*sz*cx;
- m[0,2]:=-mx*sz*sx;
-
- m[1,0]:=-my*sz;
- m[1,1]:= my*cz*cx;
- m[1,2]:=-my*cz*sx;
-
- m[2,0]:= 0.0;
- m[2,1]:=-mz*sx;
- m[2,2]:=-mz*cx;
- END;
-
- RESULT.dz:=2.0*SQRT(LONGREAL(area.w)^2.+LONGREAL(area.h)^2.);
-
- RESULT.x:=area.x+area.w DIV 2;
- RESULT.y:=area.y+area.h DIV 2;
-
- RESULT.light:=VMMul(MInvert(RESULT.rotateNScale),LightVects[draw.light]);
- VNorm(RESULT.light);
-
- END CalcConvParams;
-
- PROCEDURE Conv3dTo2d(REF conv : ConvParams;
- REF pos : Vector;
- VAR x,y : INTEGER);
- VAR v : Vector;
- BEGIN
- v:=VMMul(conv.rotateNScale,VAdd(pos,conv.add));
- x:=INTEGER(conv.dz*v[0]/(v[2]+conv.dz))+conv.x;
- y:=INTEGER(conv.dz*v[1]/(v[2]+conv.dz))+conv.y;
- END Conv3dTo2d;
-
- PROCEDURE RenderFunction( rast : RastPortPtr;
- REF area : ResBox;
- REF func : FuncParams;
- REF draw : DrawParams;
- break : Break);
-
- TYPE
- DrawRectProc = PROCEDURE(v00,v01,v10,v11 : Vector);
-
- VAR
- conv : ConvParams;
-
- PROCEDURE TraceIt;
- VAR f : Function;
- minX,maxX,
- minY,maxY,
- minZ,maxZ : LONGREAL;
- rred,
- rgreen,
- rblue : LONGREAL;
-
- revmat : Matrix;
- view,dir : Vector;
- dirx,diry,dirz : Vector;
-
- x,y : INTEGER;
- color : Vector;
- r,g,b : INTEGER;
-
- light : Vector;
-
- DeltaRay : LONGREAL;
-
- PROCEDURE CalcDxF(x,y : LONGREAL):LONGREAL;
- BEGIN
- RETURN (f.Eval(x+0.01,y)-f.Eval(x,y))/0.01;
- END CalcDxF;
-
- PROCEDURE CalcDyF(x,y : LONGREAL):LONGREAL;
- BEGIN
- RETURN (f.Eval(x,y+0.01)-f.Eval(x,y))/0.01;
- END CalcDyF;
-
- EXCEPTION NoCutPoint : "No cut point";
-
- CONST
- HalfIter = 6;
-
- |
- | p : Stuetzpunkt
- | n : Richtung (normalisiert !!!)
- |
- PROCEDURE IntersectRay(p,n : Vector):Vector;
- VAR r : LONGREAL;
- pleft,pright : Vector;
- i : INTEGER;
- BEGIN
- IF p[2]>maxZ THEN
- ASSERT(n[2]<0,NoCutPoint);
- p[0]:=p[0]-n[0]*(p[2]-func.maxZ)/n[2];
- p[1]:=p[1]-n[1]*(p[2]-func.maxZ)/n[2];
- p[2]:=func.maxZ;
- END;
- n:=VExt(n,DeltaRay);
- REPEAT
- p:=VAdd(p,n);
- r:=f.Eval(p[0],p[1]);
- UNTIL (p[2]<r) OR (p[0]<minX) AND (n[0]<0.)
- OR (p[0]>maxX) AND (n[0]>0.)
- OR (p[1]<minY) AND (n[1]<0.)
- OR (p[1]>maxY) AND (n[1]>0.)
- OR (p[2]>maxZ) AND (n[2]>0.);
- ASSERT(p[2]<r,NoCutPoint);
- pleft:=VSub(p,n);
- pright:=p;
- FOR i:=1 TO HalfIter DO
- p[0]:=(pleft[0]+pright[0])/2.0;
- p[1]:=(pleft[1]+pright[1])/2.0;
- p[2]:=(pleft[2]+pright[2])/2.0;
- r:=f.Eval(p[0],p[1]);
- IF p[2]<r THEN
- pright:=p
- ELSE
- pleft:=p;
- END;
- END;
- ASSERT((p[0]>=minX) AND
- (p[0]<=maxX) AND
- (p[1]>=minY) AND
- (p[1]<=maxY) AND
- (p[2]<=maxZ) ,NoCutPoint);
- RESULT[0]:=(pleft[0]+pright[0])/2.0;
- RESULT[1]:=(pleft[1]+pright[1])/2.0;
- RESULT[2]:=f.Eval(RESULT[0],RESULT[1]);
- END IntersectRay;
-
- PROCEDURE CheckRay(p,n : Vector):BOOLEAN;
- VAR r : LONGREAL;
- pleft,pright : Vector;
- i : INTEGER;
- BEGIN
- n:=VExt(n,DeltaRay);
- REPEAT
- p:=VAdd(p,n);
- r:=f.Eval(p[0],p[1]);
- UNTIL (p[2]<r) OR (p[0]<minX) OR (p[0]>maxX) OR
- (p[1]<minY) OR (p[1]>maxY) OR
- (p[2]>maxZ);
- RETURN p[2]<r;
- END CheckRay;
-
- PROCEDURE NormVector(p : Vector):Vector;
- BEGIN
- RESULT[0]:=-CalcDxF(p[0],p[1]);
- RESULT[1]:=-CalcDyF(p[0],p[1]);
- RESULT[2]:=1.0;
- VNorm(RESULT);
- END NormVector;
-
- PROCEDURE CalcLight(n : Vector):LONGREAL;
- VAR r : LONGREAL;
- BEGIN
- r:=light[0]*n[0]+light[1]*n[1]+light[2]*n[2];
- IF r<0.0 THEN
- r:=0.0
- END;
- RETURN r;
- END CalcLight;
-
- PROCEDURE CalcColor(p,n : Vector;depth : INTEGER := 10):Vector;
- VAR hit,norm : Vector;
- hit2 : Vector;
- l,spec : LONGREAL;
- co,co2 : Vector;
- t : LONGREAL;
- BEGIN
- IF depth=0 THEN
- RESULT:=Vector:(0.0,0.0,0.0)
- ELSE
- DEC(depth);
- VNorm(n);
- TRY
- hit:=IntersectRay(p,n);
- norm:=NormVector(hit);
- l:=CalcLight(norm);
- IF draw.shadows AND (l>0) THEN
- IF CheckRay(hit,light) THEN
- l:=0.0
- END;
- END;
- IF draw.specular THEN
- spec:=0.7*l^16.0;
- l:=l*0.6+0.1;
- co[0]:=l*rred+spec;
- co[1]:=l*rgreen+spec;
- co[2]:=l*rblue+spec;
- ELSE
- l:=l*0.9+0.1;
- co[0]:=l*rred;
- co[1]:=l*rgreen;
- co[2]:=l*rblue;
- END;
- IF draw.mirror THEN
- t:=-2.0*(n[0]*norm[0]+n[1]*norm[1]+n[2]*norm[2]);
- n[0]:=n[0]+t*norm[0];
- n[1]:=n[1]+t*norm[1];
- n[2]:=n[2]+t*norm[2];
- co2:=CalcColor(hit,n,depth);
- RESULT[0]:=co[0]*0.5+co2[0]*0.6;
- RESULT[1]:=co[1]*0.5+co2[1]*0.6;
- RESULT[2]:=co[2]*0.5+co2[2]*0.6;
- ELSE
- RESULT:=co;
- END;
- EXCEPT
- OF NoCutPoint THEN
- RESULT[0]:=(1.0-n[2])*0.5;
- RESULT[1]:=(1.0-n[2])*0.5;
- RESULT[2]:=(1.0-n[2])*0.7;
- END;
- END;
- END;
- END CalcColor;
-
- PROCEDURE SQR(x : LONGREAL):LONGREAL;
- BEGIN
- RETURN x*x;
- END SQR;
-
- BEGIN
- minX:=func.minX;
- maxX:=func.maxX;
- minY:=func.minY;
- maxY:=func.maxY;
- minZ:=func.minZ;
- maxZ:=func.maxZ;
-
- DeltaRay:=SQRT(SQR(maxX-minX)+SQR(maxY-minY)+SQR(maxZ-minZ))/40; |Schätzwert
-
- f.Create(func.funcStr,NIL,"x","y");
- rred :=LONGREAL(draw.fColor.red)/255.0;
- rgreen:=LONGREAL(draw.fColor.green)/255.0;
- rblue :=LONGREAL(draw.fColor.blue)/255.0;
-
- revmat:=MInvert(conv.rotateNScale);
-
- view[0]:=0.0;
- view[1]:=0.0;
- view[2]:=-conv.dz;
- view:=VAdd(VMMul(revmat,view),conv.add);
-
- light:=VNeg(conv.light);
-
- dirz[0]:=0.0;
- dirz[1]:=0.0;
- dirz[2]:=conv.dz;
- dirz:=VMMul(revmat,dirz);
-
- dirx:=VMMul(revmat,Vector:(1.0,0.0,0.0));
- diry:=VMMul(revmat,Vector:(0.0,1.0,0.0));
-
- dirz:=VAdd(dirz,VExt(dirx,-LONGREAL(area.w DIV 2)),
- VExt(diry,-LONGREAL(area.h DIV 2)));
-
- FOR y:=0 TO area.h-1 DO
- dir:=dirz;
- IF draw.renderMap#NIL THEN
- FOR x:=0 TO area.w-1 DO
- color:=CalcColor(view,dir);
- r:=INTEGER(color[0]*255.);IF r<0 THEN r:=0 OR_IF r>255 THEN r:=255 END;
- g:=INTEGER(color[1]*255.);IF g<0 THEN g:=0 OR_IF g>255 THEN g:=255 END;
- b:=INTEGER(color[2]*255.);IF b<0 THEN b:=0 OR_IF b>255 THEN b:=255 END;
- WritePixel(draw.renderMap,LONGINT(r) SHL 24+
- LONGINT(g) SHL 16+
- LONGINT(b) SHL 8,
- x,y,{});
- dir:=VAdd(dir,dirx);
- END;
- G.CopyBitMapRastPort(draw.renderMap,rast,0,y,area.w,1,area.x,area.y+y);
- ELSE
- FOR x:=0 TO area.w-1 DO
- color:=CalcColor(view,dir);
- r:=INTEGER(color[0]*255.);IF r<0 THEN r:=0 OR_IF r>255 THEN r:=255 END;
- g:=INTEGER(color[1]*255.);IF g<0 THEN g:=0 OR_IF g>255 THEN g:=255 END;
- b:=INTEGER(color[2]*255.);IF b<0 THEN b:=0 OR_IF b>255 THEN b:=255 END;
- G.SetAPen(rast,LONGINT(r) SHL 24+
- LONGINT(g) SHL 16+
- LONGINT(b) SHL 8);
- G.WritePixel(rast,x+area.x,y+area.y);
- dir:=VAdd(dir,dirx);
- END;
- END;
- dirz:=VAdd(dirz,diry);
- IF break() THEN
- f.Delete;
- RETURN
- END;
- END;
-
- f.Delete;
- END TraceIt;
-
- PROCEDURE RenderIt(call : DrawRectProc);
- VAR x,y : INTEGER;
- prevRow : ARRAY [256] OF LONGREAL;
- v00,v01,v10,v11 : Vector;
- xr,yr,dx,dy,xs : LONGREAL;
- num : INTEGER;
- f : Function;
- BEGIN
- f.Create(func.funcStr,NIL,"x","y");
-
- num:=1 SHL draw.resolution;
- dy:=(func.maxY-func.minY)/LONGREAL(num);
- yr:=func.minY;
-
- IF draw.bearing<0 THEN
- dx:=(func.minX-func.maxX)/LONGREAL(num);
- xs:=func.maxX;
- ELSE
- dx:=(func.maxX-func.minX)/LONGREAL(num);
- xs:=func.minX;
- END;
-
- xr:=xs;
-
- FOR x:=0 TO num DO
- prevRow[x]:=f.Eval(xr,yr);
- xr:=xr+dx;
- END;
- FOR y:=1 TO num DO
- v10[1]:=yr;v11[1]:=yr;
- yr:=yr+dy;
- v00[1]:=yr;v01[1]:=yr;
- xr:=xs;
- v10[2]:=prevRow[0];
- v00[2]:=f.Eval(xr,yr);
- FOR x:=1 TO num DO
- v00[0]:=xr;v10[0]:=xr;
- xr:=xr+dx;
- v01[0]:=xr;v11[0]:=xr;
- v11[2]:=prevRow[x];
- v01[2]:=f.Eval(xr,yr);
- IF draw.bearing<0 THEN
- call(v00,v10,v01,v11);
- ELSE
- call(v00,v01,v10,v11);
- END;
- prevRow[x-1]:=v00[2];
- v10[2]:=v11[2];
- v00[2]:=v01[2];
- END;
- prevRow[num]:=v00[2];
- IF break() THEN
- f.Delete;
- RETURN
- END;
- END;
-
- f.Delete;
- END RenderIt;
-
- PROCEDURE WireFrame(v00,v01,v10,v11 : Vector);
- VAR x00,x01,x10,x11 : INTEGER;
- y00,y01,y10,y11 : INTEGER;
- BEGIN
- Conv3dTo2d(conv,v00,x00,y00);
- Conv3dTo2d(conv,v01,x01,y01);
- Conv3dTo2d(conv,v10,x10,y10);
- Conv3dTo2d(conv,v11,x11,y11);
-
- G.SetAPen(rast,0);
- G.Move(rast,x00,y00);
- G.Draw(rast,x01,y01);
- G.Draw(rast,x11,y11);
- G.Draw(rast,x10,y10);
- G.Draw(rast,x00,y00);
- END WireFrame;
-
- PROCEDURE Flat(v00,v01,v10,v11 : Vector);
- VAR x00,x01,x10,x11 : INTEGER;
- y00,y01,y10,y11 : INTEGER;
- BEGIN
- Conv3dTo2d(conv,v00,x00,y00);
- Conv3dTo2d(conv,v01,x01,y01);
- Conv3dTo2d(conv,v10,x10,y10);
- Conv3dTo2d(conv,v11,x11,y11);
-
- G.SetAPen(rast,draw.fPen);
- G.AreaMove(rast,x00,y00);
- G.AreaDraw(rast,x01,y01);
- G.AreaDraw(rast,x11,y11);
- G.AreaDraw(rast,x10,y10);
- G.AreaDraw(rast,x00,y00);
- G.AreaEnd(rast);
- IF draw.outlined THEN
- G.SetAPen(rast,$00000000);
- G.Move(rast,x00,y00);
- G.Draw(rast,x01,y01);
- G.Draw(rast,x11,y11);
- G.Draw(rast,x10,y10);
- G.Draw(rast,x00,y00);
- END;
- END Flat;
-
- PROCEDURE Shaded(v00,v01,v10,v11 : Vector);
- VAR x00,x01,x10,x11 : INTEGER;
- y00,y01,y10,y11 : INTEGER;
- norm : Vector;
- light : INTEGER;
- BEGIN
- Conv3dTo2d(conv,v00,x00,y00);
- Conv3dTo2d(conv,v01,x01,y01);
- Conv3dTo2d(conv,v10,x10,y10);
- Conv3dTo2d(conv,v11,x11,y11);
-
- norm:=VCMul(VSub(v00,v11),VSub(v01,v10));
- VNorm(norm);
- light:=INTEGER(256.0*VSMul(norm,conv.light));
- IF light<10 THEN light:=10
- OR_IF light>256 THEN light:=256 END;
- G.SetAPen(rast,LMUL(light,INTEGER(draw.fColor.red)) DIV 256 SHL 24+
- LMUL(light,INTEGER(draw.fColor.green)) DIV 256 SHL 16+
- LMUL(light,INTEGER(draw.fColor.blue)) DIV 256 SHL 8);
- G.AreaMove(rast,x00,y00);
- G.AreaDraw(rast,x01,y01);
- G.AreaDraw(rast,x11,y11);
- G.AreaDraw(rast,x10,y10);
- G.AreaDraw(rast,x00,y00);
- G.AreaEnd(rast);
- IF draw.outlined THEN
- G.SetAPen(rast,$00000000);
- G.Move(rast,x00,y00);
- G.Draw(rast,x01,y01);
- G.Draw(rast,x11,y11);
- G.Draw(rast,x10,y10);
- G.Draw(rast,x00,y00);
- END;
- END Shaded;
-
- PROCEDURE Specular(v00,v01,v10,v11 : Vector);
- VAR x00,x01,x10,x11 : INTEGER;
- y00,y01,y10,y11 : INTEGER;
- norm : Vector;
- light,spec : LONGREAL;
- red,green,blue : LONGINT;
- BEGIN
- Conv3dTo2d(conv,v00,x00,y00);
- Conv3dTo2d(conv,v01,x01,y01);
- Conv3dTo2d(conv,v10,x10,y10);
- Conv3dTo2d(conv,v11,x11,y11);
-
- norm:=VCMul(VSub(v00,v11),VSub(v01,v10));
- VNorm(norm);
- light:=VSMul(norm,conv.light);
- IF light<0 THEN light:=0 END;
- spec:=light^16.0*192.;
- light:=light*0.9+0.1;
-
- red :=LONGINT(LONGREAL(draw.fColor.red )*light+spec);
- green:=LONGINT(LONGREAL(draw.fColor.green)*light+spec);
- blue :=LONGINT(LONGREAL(draw.fColor.blue )*light+spec);
-
- IF red >255 THEN red :=255 END;
- IF green>255 THEN green:=255 END;
- IF blue >255 THEN blue :=255 END;
-
-
- G.SetAPen(rast,red SHL 24+
- green SHL 16+
- blue SHL 8);
-
- G.AreaMove(rast,x00,y00);
- G.AreaDraw(rast,x01,y01);
- G.AreaDraw(rast,x11,y11);
- G.AreaDraw(rast,x10,y10);
- G.AreaDraw(rast,x00,y00);
- G.AreaEnd(rast);
- IF draw.outlined THEN
- G.SetAPen(rast,$00000000);
- G.Move(rast,x00,y00);
- G.Draw(rast,x01,y01);
- G.Draw(rast,x11,y11);
- G.Draw(rast,x10,y10);
- G.Draw(rast,x00,y00);
- END;
- END Specular;
-
- VAR rect : ClipRect;
-
- BEGIN
- conv:=CalcConvParams(area,func,draw);
- rect.next:=NIL;
- rect.left:=area.x;
- rect.top :=area.y;
- rect.right:=area.x+area.w-1;
- rect.bottom:=area.y+area.h-1;
- G.InstallClipRegion(rast,rect'PTR);
- G.SetAPen(rast,draw.bPen);
- G.RectangleFill(rast,area.x,area.y,area.w,area.h);
- IF KEY draw.mode
- OF wire THEN RenderIt(WireFrame) END
- OF solid THEN RenderIt(Flat) END
- OF shaded THEN
- IF draw.specular THEN
- RenderIt(Specular);
- ELSE
- RenderIt(Shaded);
- END;
- END
- OF traced THEN TraceIt END;
- END;
- FORGET G.RemoveClipRegion(rast);
- END RenderFunction;
-
- PROCEDURE AxisMove( rast : RastPortPtr;
- REF area : ResBox;
- VAR draw : DrawParams;
- pitch : Pitch;
- bearing : Bearing);
- CONST
- func = FuncParams:(minX=-1,maxX=1,
- minY=-1,maxY=1,
- minZ=-1,maxZ=1);
-
- VAR
- conv : ConvParams;
- midx,midy : INTEGER;
- axx,axy : INTEGER;
- arx,ary : INTEGER;
- rect : ClipRect;
-
- BEGIN
- IF (pitch#draw.pitch) OR (bearing#draw.bearing) THEN
- draw.pitch:=pitch;
- draw.bearing:=bearing;
- conv:=CalcConvParams(area,func,draw);
-
- rect.next:=NIL;
- rect.left:=area.x;
- rect.top :=area.y;
- rect.right:=area.x+area.w-1;
- rect.bottom:=area.y+area.h-1;
- G.InstallClipRegion(rast,rect'PTR);
-
- G.SetAPen(rast,draw.bPen);
- G.RectangleFill(rast,area.x,area.y,area.w,area.h);
- G.SetAPen(rast,$00000000);
- Conv3dTo2d(conv,Vector:(0.0,0.0,0.0),midx,midy);
-
- Conv3dTo2d(conv,Vector:(1.0,0.0,0.0),axx,axy);
- G.Move(rast,midx,midy);
- G.Draw(rast,axx,axy);
- Conv3dTo2d(conv,Vector:(0.9,0.1,0.0),arx,ary);
- G.Draw(rast,arx,ary);
- G.Move(rast,axx,axy);
- Conv3dTo2d(conv,Vector:(0.9,-0.1,0.0),arx,ary);
- G.Draw(rast,arx,ary);
-
- Conv3dTo2d(conv,Vector:(0.0,1.0,0.0),axx,axy);
- G.Move(rast,midx,midy);
- G.Draw(rast,axx,axy);
- Conv3dTo2d(conv,Vector:(0.1,0.9,0.0),arx,ary);
- G.Draw(rast,arx,ary);
- G.Move(rast,axx,axy);
- Conv3dTo2d(conv,Vector:(-0.1,0.9,0.0),arx,ary);
- G.Draw(rast,arx,ary);
-
- Conv3dTo2d(conv,Vector:(0.0,0.0,1.0),axx,axy);
- G.Move(rast,midx,midy);
- G.Draw(rast,axx,axy);
- Conv3dTo2d(conv,Vector:(0.1,0.0,0.9),arx,ary);
- G.Draw(rast,arx,ary);
- G.Move(rast,axx,axy);
- Conv3dTo2d(conv,Vector:(-0.1,0.0,0.9),arx,ary);
- G.Draw(rast,arx,ary);
-
- FORGET G.RemoveClipRegion(rast);
- END;
- END AxisMove;
-
-
- END Render.
-